#pragma once

#include <Windows.h>
#include <string>
#include <sstream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
class Utils
{
public:
	static string GetGUID()
	{
		UCHAR *pszUuid = 0x00;

		GUID *pguid = 0x00;

		pguid = new GUID;

		CoCreateGuid(pguid);

		// Convert the GUID to a string
		UuidToString(pguid, &pszUuid);
		delete pguid; 

		ostringstream out;
		out << pszUuid;

		RpcStringFree(&pszUuid);

		return out.str();
	}

	static string GetLocalComputerName() { 
		TCHAR chrComputerName[MAX_COMPUTERNAME_LENGTH + 1]; 
		string strRetVal; 
		DWORD dwBufferSize = MAX_COMPUTERNAME_LENGTH + 1; 

		if(GetComputerName(chrComputerName,&dwBufferSize)) { 
			// We got the name, set the return value. 
			strRetVal = chrComputerName; 
		} else { 
			// Failed to get the name, call GetLastError here to get 
			// the error code. 
			strRetVal = ""; 
		} 

		return(strRetVal); 
	}

	static string GetLocalIp()
	{
		// Add 'ws2_32.lib' to your linker options

		WSADATA WSAData;

		// Initialize winsock dll
		if(::WSAStartup(MAKEWORD(1, 0), &WSAData))
		{
			// Error handling
		}

		// Get local host name
		char szHostName[128] = "";

		if(::gethostname(szHostName, sizeof(szHostName)))
		{
			// Error handling -> call 'WSAGetLastError()'
		}

		// Get local IP addresses
		struct sockaddr_in SocketAddress;
		struct hostent     *pHost        = 0;

		pHost = ::gethostbyname(szHostName);
		if(!pHost)
		{
			// Error handling -> call 'WSAGetLastError()'
		}

		char aszIPAddresses[10][16]; // maximum of ten IP addresses

		for(int iCnt = 0; ((pHost->h_addr_list[iCnt]) && (iCnt < 10)); ++iCnt)
		{
			memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[iCnt], pHost->h_length);
			strcpy_s(aszIPAddresses[iCnt], inet_ntoa(SocketAddress.sin_addr));
		}

		// Cleanup
		WSACleanup();

		return aszIPAddresses[0];
	}


	static string GetRandomPipeName()
	{
		string pipeName = "\\\\.\\pipe\\";
		return pipeName.append(Utils::GetGUID().substr(0,6));
	}

	static inline int RandInt(int x, int y) 
	{
		srand(static_cast<UINT>(__rdtsc()));
		return rand()%(y-x+1)+x;
	}

	static inline char GetRandomChar()
	{
		if( RandInt(0,10) > 6)
		{
			// 40% de probabilidades de calhar uma letra qualquer
			int a = Utils::RandInt(0, 25);
			return static_cast<char>(65 + a );
		}

		// 60% de probabilidades de calhar uma vogal
		char vogals[] = {'A','E','I','O','U'};
		return vogals[Utils::RandInt(0, 4)];
	}



	static void WriteLog(const char* msg)
	{
		static HANDLE mWriteLogSem =  CreateSemaphore(NULL, 1, 1, NULL);
		WaitForSingleObject(mWriteLogSem, INFINITE);
			FILE * pFile;
			fopen_s (&pFile, "c:\\TPSO2\\log.txt","a");
			if (pFile!=NULL)
			{
				fputs (msg,pFile);
				fputc('\n',pFile);
				fclose (pFile);
			}

			ReleaseSemaphore(mWriteLogSem, 1, NULL);

	}

	static void WriteLog(const char* msg, DWORD _number)
	{
		ostringstream os;
		os << msg << _number;
		Utils::WriteLog(os.str().c_str());
	}
};
